home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 301-325 / disk_319 / cnewssrc / cnews.src.lzh / relay / active.c next >
C/C++ Source or Header  |  1989-08-01  |  6KB  |  263 lines

  1. /*
  2.  * active file access functions
  3.  */
  4.  
  5. #ifdef DEBUG
  6. #  define STAT(x)    {    fprintf(stderr,"%s: %d, ",__FUNC__,__LINE__);\
  7.                         fprintf x;\
  8.                         fflush(stderr); }
  9. #else
  10. #  define STAT(x)
  11. #endif
  12.  
  13. #include <stdio.h>
  14. #include <ctype.h>
  15. #if 0
  16. # include <sys/types.h>
  17. # include <sys/stat.h>        /* Why is this included??? */
  18. #endif
  19. #include "libc.h"
  20. #include "news.h"
  21. #include "config.h"
  22. #include "active.h"
  23.  
  24. /* ordinal numbers of fields */
  25. #define CURRFIELD 2        /* current article # */
  26. #define FLAGFIELD 4        /* y/n/m/x/= flag */
  27.  
  28. /* flag field values */
  29. #define FLAGOKAY 'y'        /* ordinary unmoderated group */
  30. #define FLAGBAD 'n'        /* unmoderated but locally-restricted group */
  31. #define FLAGMOD 'm'        /* moderated group */
  32. #define FLAGNEVER 'x'        /* unwanted group: don't file in this one */
  33. #define FLAGGOTO '='        /* see another group (following) instead */
  34.  
  35. /* imports */
  36. extern char *actfind();
  37. extern statust actfload(), actfsync(), actfwrnum();
  38.  
  39. /* forwards */
  40. extern char *findflag();
  41. FORWARD char *fieldfind();
  42.  
  43. /* exports */
  44. char actrelnm[] = "active";
  45.  
  46. static FILE *actfp = NULL;
  47. static struct lastngcache {
  48.     char *lnc_ng;            /* newsgroup name */
  49.     char *lnc_line;            /* matching active file line */
  50. } lnc = { NULL, NULL };
  51.  
  52. /*
  53.  * return a pointer to the active file entry for ng
  54.  * (or a pointed-to group (by ``=group'')), or 0 if no entry exists.
  55.  * since actlook is called repeatedly for the same newsgroup,
  56.  * actlook caches the last newsgroup looked-up and the result.
  57.  */
  58.  
  59. STATIC char *actlook(ang)
  60. register char *ang;
  61. {
  62.     register char *ngline, *ng, *flag;
  63.     register int loopbreak = 100;
  64.  
  65.     STAT((stderr, "cache check\n"));
  66.     if (lnc.lnc_ng != NULL && STREQ(lnc.lnc_ng, ang))
  67.         return lnc.lnc_line;
  68.  
  69.     STAT((stderr, "calling actload()\n"));
  70.     if (actload() != ST_OKAY) {
  71.         STAT((stderr, "actload() didn't work!\n"));
  72.         return NULL;
  73.     }
  74.     STAT((stderr, "calling strsave(\"%s\")\n", ang));
  75.     ng = strsave(ang);
  76.     while ((ngline = actfind(actfp, ng, strlen(ng))) != NULL &&
  77.             (flag = findflag(ngline)) != NULL && *flag == FLAGGOTO &&
  78.             --loopbreak > 0) {
  79.         STAT((stderr, "actfind() got `%s'\n", ngline));
  80.         free(ng);
  81.         ng = strsvto(flag+1, '\n');    /* follow "=ng" pointer */
  82.     }
  83.     STAT((stderr,
  84.         "use newsgroup ``%.*s''\n", index(ngline,'\n') - ngline, ngline));
  85.     if (loopbreak <= 0)            /* "infinite" loop broken */
  86.         ngline = NULL;
  87.  
  88.     STAT((stderr, "calling nnfree()\n"));
  89.     nnfree(&lnc.lnc_ng);
  90.     lnc.lnc_ng = ng;
  91.     lnc.lnc_line = ngline;
  92.     return ngline;
  93. }
  94.  
  95. /*
  96.  * Find the active entry for ng (or a pointed-to group (by ``=group''))
  97.  * and add inc to its 2nd field (highest number).
  98.  * Return the resultant number.
  99.  */
  100.  
  101. long incartnum(ng, inc)
  102. char *ng;
  103. int inc;
  104. {
  105.     char testnum[40];
  106.     register char *line = actlook(ng);
  107.     register long nextart = -1;
  108.  
  109.     if (line != NULL) {
  110.         register char *artnum, *pastartnum;
  111.  
  112.         STAT((stderr, "found `active' line: %.*s\n",
  113.             index(line, '\n') - line, line));
  114.         pastartnum = artnum = fieldfind(line, CURRFIELD);
  115.         if (artnum == NULL)
  116.             return nextart;
  117.         while (isascii(*pastartnum) && isdigit(*pastartnum))
  118.             ++pastartnum;
  119.         nextart = atol(artnum) + inc;
  120.  
  121.         /* update active file article # in place, from nextart */
  122.         if (pastartnum-artnum > sizeof testnum ||
  123.             !ltozan(testnum, nextart, pastartnum-artnum) ||
  124.             !ltozan(artnum, nextart, pastartnum-artnum)) {
  125.             (void) fprintf(stderr,
  126. "%s: article number (%ld) too big for group `%s' active field of %d digits\n",
  127.                 progname, nextart, ng, pastartnum-artnum);
  128.             return -1;
  129.         }
  130.  
  131.         /* give the implementation a chance to write line to disk */
  132.         if (actfwrnum(actfp, line) != ST_OKAY) {
  133.             warning("can't update active file", "");
  134.             nextart = -1;
  135.         }
  136.     }
  137.     return nextart;
  138. }
  139.  
  140. /*
  141.  * Reload the active file cache.
  142.  */
  143.  
  144. statust actload()
  145. {
  146.     register statust status = ST_OKAY;
  147.  
  148.     if (actfp == NULL &&
  149.                 (actfp = fopenwclex(ctlfile(actrelnm), "r+")) == NULL)
  150.         status |= ST_DROPPED;
  151.     STAT((stderr, "about to call actfload()\n"));
  152.     status |= actfload(actfp);
  153.     return status;
  154. }
  155.  
  156. /*
  157.  * Write back to disk the active file cache, if any, and flush the
  158.  * last-newsgroup-cache, since it refers to the (now invalid) active file
  159.  * cache.
  160.  */
  161.  
  162. statust actsync()
  163. {
  164.     register statust status = ST_OKAY;
  165.  
  166.     if (actfp != NULL) {
  167.         lnc.lnc_ng = lnc.lnc_line = NULL;
  168.         status |= actfsync(actfp);
  169.         if (nfclose(actfp) == EOF || status != ST_OKAY) {
  170.             warning("error writing `%s'", ctlfile(actrelnm));
  171.             status |= ST_DROPPED;
  172.         }
  173.     }
  174.     actfp = NULL;
  175.     return status;
  176. }
  177.  
  178. /*
  179.  * Return YES iff any group in ngs (or a pointed-to group (by ``=group''))
  180.  * matches thisflag.
  181.  */
  182.  
  183. boolean isflag(ngs, thisflag)
  184. register char *ngs;
  185. int thisflag;
  186. {
  187.     register char *newng, *flag, *ng;
  188.     register boolean result = NO;
  189.  
  190.     for (ng = ngs; !result && ng != NULL; ng = newng) {
  191.         newng = index(ng, NGSEP);
  192.         if (newng != NULL)
  193.             *newng = '\0';        /* restored below */
  194.  
  195.         flag = findflag(actlook(ng));
  196.         if (flag != NULL && *flag == thisflag)
  197.             result = YES;
  198.  
  199.         if (newng != NULL)
  200.             *newng++ = NGSEP;    /* point at next group */
  201.     }
  202.     return result;
  203. }
  204.  
  205. /* return address of field "fieldno" in ngline */
  206. STATIC char *fieldfind(ngline, fieldno)
  207. register char *ngline;
  208. register int fieldno;
  209. {
  210.     register int field;
  211.  
  212.     for (field = 1; ngline != NULL && field < fieldno; ++field) {
  213.         ngline = index(ngline, ' ');
  214.         if (ngline != NULL)
  215.             ngline++;        /* point at next field */
  216.     }
  217.     return ngline;
  218. }
  219.  
  220. char *findflag(ngline)        /* return address of flag field in ngline */
  221. register char *ngline;
  222. {
  223.     return fieldfind(ngline, FLAGFIELD);
  224. }
  225.  
  226. /*
  227.  * Are any groups in ngs moderated?
  228.  */
  229.  
  230. boolean moderated(ngs)
  231. register char *ngs;
  232. {
  233.     return isflag(ngs, FLAGMOD);
  234. }
  235.  
  236. /*
  237.  * Are any groups in ngs unwanted?
  238.  */
  239.  
  240. boolean unwanted(ngs)
  241. register char *ngs;
  242. {
  243.     return isflag(ngs, FLAGNEVER);
  244. }
  245.  
  246. /*
  247.  * Return 0 or a malloced newsgroup name corresponding to "ong",
  248.  * but without an "=" flag in its active file entry.
  249.  *
  250.  * This is done by tracing the chain of "=ng" pointers (in actlook()),
  251.  * if any.
  252.  */
  253.  
  254. char *realngname(ong)
  255. char *ong;
  256. {
  257.     register char *ngline = actlook(ong);
  258.  
  259.     if (ngline == NULL)
  260.         return NULL;            /* no such ong */
  261.     return strsvto(ngline, ' ');
  262. }
  263.